#include <yatak/yatak.h>
#include <yatak/debug.h>
#include <yatak/kheap.h>
#include <screen.h>
#include <string.h>
#include <shell.h>
#include <sched.h>
#include <time.h>

#define NUM_TESTS 1
#define ALLOC_TASK 20

static char res_tests [NUM_TESTS] [3] [256];

// alloc tests
static int alloc_addr [ALLOC_TASK*2] = {0};
static int num_test = 0;
static int arr_alloc_addr [ALLOC_TASK] = {0};
static pid_t alloc_tasks [ALLOC_TASK] = {0};

static void Start_alloc_test ();
static void Clear_alloc_test ();
static void create_alloc_task (int num);
static void create_alloc_res (int * arr, int size);
static void print_all_res ();

void module_mem_test ()
{
	systime test_time;
	char str_test_time [256];
	unsigned int start_time, end_time;
	printf ("Start memory tests...\nPlease wait!\n");
	start_time = get_time_sec ();
	Start_alloc_test ();
	Clear_alloc_test ();
	create_alloc_res (alloc_addr, ALLOC_TASK*2);
	end_time = get_time_sec ();
	get_time_count (&test_time, start_time, end_time);
	get_str_time (str_test_time, test_time);
	strcpy(res_tests [num_test] [2],str_test_time);
	num_test++;
	print_all_res ();
}

static void Start_alloc_test ()
{
	int i = 0;
	for (i = 0; i < ALLOC_TASK*2; i+=2)
		start_task("alloc_test",true, create_alloc_task, 1, i);
}

static void create_alloc_task (int num)
{
	alloc_addr [num] = (int)GetTask(get_current_pid());
	char * arr = (char *)kmalloc(sizeof(char)*100);
	arr_alloc_addr [num/2] = alloc_addr [num+1] = (int)arr;
	alloc_tasks [num/2] = get_current_pid();
	//kfree (arr);
	for (;;);
}

static void Clear_alloc_test ()
{
	int i;
	for (i = 0; i < ALLOC_TASK; i++)
	{
		kfree (arr_alloc_addr[i]);
		if (kill_task(alloc_tasks[i]))
			dprintf ("[Clear_alloc_test] Cannot delete task pid %d\n",alloc_tasks[i]);
	}
}

static void create_alloc_res (int * arr, int size)
{
	strcpy(res_tests [num_test] [0],"Secure alloc test");
	int failed = 0;
	int i = 0, j = 0;
	for (i = 0; i < size; i++)
	{
		for (j = 0; j < size; j++)
		{
			if (i != j && arr [i] == arr [j])
			{
				failed++;
				break;
			}
		}
	}
	sprintf(res_tests [num_test] [1],"total: %d passed: %d failed %d", size, size-failed, failed);
}

static void print_all_res ()
{
	unsigned int flags;
	save_flags (flags);
	cli ();
	kprintf("\n");
	int i;
	for (i = 0; i < NUM_TESTS; i++)
		kprintf ("%s: %s time: %s\n",(char *)res_tests [i] [0], (char *)res_tests [i] [1], (char *)res_tests [i] [2]);
	restore_flags (flags);
}